package com.hc.sp06.fallback;

import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import sp01.util.JsonResult;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 降级类
 * 实现接口，实现方法
 *
 * 通过zuul网关调用后台商品服务失败时，
 * 会执行这段降级代码，向客户端返回降级结果
 * Hystrix做降级的话，需要实现一个FallbackProvider这个接口
 *
 * @author Z
 * @DATE 2021/9/1 10:32
 * @e-mail ...@qq.com
 */
@Component//spring自动扫描，自动创建实例
public class OrderFB implements FallbackProvider {
    /*
    设置当前降级类是针对哪个服务的降级类
    例：只针对item-service 商品服务做降级
     调用用户或者订单服务失败，是不执行降级的
    - *:针对所有服务都应用当前降级类
    - null，他和*相同作用
     */
    @Override
    public String getRoute() {
        return "order-service";   //从项目文件读取
    }

    /*
     * 降级的放回结果
     * 发送给客户端的降级结果。
     * 要封装在Response对象中
     */
    /*
    这个方法返回的就是一个Response响应对象
    这里面包含的就是返回给客户端的响应结果
    那这个响应结果，如果做讲解处理的话，降级的结果可以是简单的错误提示
    比如”服务不可用“等等
     */
    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        //把降级结果封装在新创建的这个Response对象中
        //数据就在这些接口实现中进行设置
        return new ClientHttpResponse() {
//            返回状态码
//StatusCode是一个封装对象
//比如状态码200,状态文本"OK"
//封装了这两个值
//返回的是HTTP协议的状态
            @Override
            public HttpStatus getStatusCode() throws IOException {
                //返回一个报错信息  {code:500,text:"服务内部错"}
                return HttpStatus.INTERNAL_SERVER_ERROR;
            }

            //RawStatusCode返回的是一个int类型的整数
            //他返回的是200的值
            //单独拿出来，进行返回200
//            返回状态码的value    也可以直接写数字....
            @Override
            public int getRawStatusCode() throws IOException {
                return HttpStatus.INTERNAL_SERVER_ERROR.value();
            }
//            返回状态的对应信息
            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase();
            }
//            关闭流，暂时用不到
            @Override
            public void close() {
//                ByteArrayInputStream //不用关闭的流
            }
//            报文 请求头+请求行+请求体
//            获取协议体(响应体)
            @Override
            public InputStream getBody() throws IOException {
                String json = JsonResult.err().code(HttpStatus.INTERNAL_SERVER_ERROR.value())
                        .msg("订单服务调用失败").toString();
                //这里可以看到他的返回类型是一个输入流。
                //那咱们还得把这个json放到输入流里边给他返回回去
                return new ByteArrayInputStream(json.getBytes("utf-8"));
            }

//          响应头
            @Override
            public HttpHeaders getHeaders() {
                //返回给客户端的协议头属性
                HttpHeaders h = new HttpHeaders();
                h.add("Content-Type", "application/json;charset=utf-8");
                return h;
            }
        };
    }
}
